//implementation of table2d

template <typename T, // elem type
		typename TCoord>
class table2D
{
public:
	typedef T	typeElem;
	//typedef unsigned long long typeCnt;
	static const int DIM = 2;

//ctor
public:
	table2D(const TCoord w, const TCoord h, const T initElem)
		:m_data(w*h, initElem), m_width(w), m_height(h)
	{}

	table2D(const table2D& other)
		:m_data(other.m_data), m_width(other.m_width), m_height(other.m_height)
	{}

	table2D(const TCoord s, const T initElem)
		:m_data(s*s, initElem), m_width(s), m_height(s)
	{}

	table2D(const TCoord w, const TCoord h,
		const T *initArr)// assume continuous storage
		:m_data(initArr, initArr + w*h), m_width(w), m_height(h)
	{}

	//template <class Iter>
	//table2D(const TCoord w, const TCoord h,
	//	const Iter initArrBeg, const Iter initArrEnd)// assume continuous storage
	//	:m_data(initArrBeg, initArrEnd), m_width(w), m_height(h)
	//{}

	//interfaces:
	T& At(const TCoord x, const TCoord y)
	{
		return m_data[(size_t)y * m_width + x];
	}

	T& At(const vec<TCoord, 2>& index)
	{
		return At(index[0], index[1]);
	}

	T At(const TCoord x, const TCoord y) const
	{
		return m_data[(size_t)y * m_width + x];
	}

	T At(const vec<TCoord, 2>& index) const
	{
		return At(index[0], index[1]);
	}

	//const typeCnt CntElem() const{return m_data.size();}

	const TCoord Width() const{return m_width;}

	const TCoord Height() const{return m_height;}

	void Fill(const T& elem)
	{
		std::fill(m_data.begin(), m_data.end(), elem);
	}

	// for elem traversal
	T* Begin()	{return &m_data[0];}
	T* End()	{return (&m_data[0] + m_data.size());}

	vec<TCoord, 2> Find(const T& elem)
	{
		// if find nothing, return default (0,0)
		vec<TCoord, 2> ret;
		for(TCoord y=0; y<m_height; ++y)
			for(TCoord x=0; x<m_width; ++x)
				if(this->At(x, y) == elem)
				{
					ret[0] = x; ret[1] = y;
					return ret;
				}
		return ret;
	}
private:
	std::vector<T>	m_data;
	TCoord m_width, m_height;
};

//TODO: table3D

